<template>
  <div class="resize-table" ref="configTableCon">
    <el-table
      class="mc-table"
      :data="data"
      :highlight-current-row="light"
      ref="tableRef"
      v-loading="showLoading"
      @select="selectChange"
      @select-all="selectAll"
      :span-method="arraySpanMethod"
      :row-key="rowKey"
      border
      :max-height="height ? height : tableHeight"
    >
      <template #empty>
        <img src="@common/assets/empty.svg" alt="" />
        <p>没有查询到符合条件的记录</p>
      </template>
      <el-table-column type="selection" v-if="selection" fixed="left" width="55" :border-line="false">
      </el-table-column>
      <template v-for="item in headers">
        <!-- 父组件自定义 -->
        <el-table-column
          v-if="item.custom && item.show"
          :width="item.width || ''"
          :key="item.prop"
          :sortable="item.isSort"
          show-overflow-tooltip
          v-bind="item"
        >
          <template #default="scope">
            <slot :name="item.prop" :scope="scope" :item="item"></slot>
          </template>
        </el-table-column>
        <!-- 操作栏 -->
        <el-table-column
          v-else-if="item.prop === 'oprate' && item.show"
          :key="item.prop + 'a'"
          :sortable="item.isSort"
          v-bind="item"
          fixed="right"
          :width="item.width ? item.width : 100"
        >
          <template #default="scope">
            <slot :name="item.prop" :scope="scope" :item="item"></slot>
          </template>
        </el-table-column>
        <!-- 无需额外处理，直接渲染 -->
        <el-table-column
          v-else-if="item.show"
          v-bind="item"
          :key="item.prop + 'b'"
          show-overflow-tooltip
        ></el-table-column>
      </template>
      <!-- 表头自定义 -->
      <el-table-column fixed="right" width="56" :resizable="false">
        <template #header>
          <el-dropdown trigger="click" @visible-change="isClick = !isClick">
            <span class="el-dropdown-link" v-show="headersConfig" :style="{ background: isClick ? '#E6E6E6' : '' }">
              <i class="MC_iconfont MC_icon-shezhi" :class="isClick ? 'icon-active' : ''"></i>
            </span>
            <template #dropdown>
              <search-checkbox :headerData="headers" @onCheckChange="handleCheckChange"></search-checkbox>
            </template>
          </el-dropdown>
        </template>
      </el-table-column>
    </el-table>
    <!-- 批量操作栏 -->
    <div class="batch-oprate" v-if="isAllCheck ? pagingData.total : selectLength">
      <el-checkbox v-model="isAllCheck" @change="checkAllData" v-if="showIsAllCheckBox">全选</el-checkbox>
      <span class="selected-count"
        >已选择<span class="selectedNum">{{ isAllCheck ? pagingData.total : selectLength }}</span
        >项</span
      >
      <div class="selectedBtn" v-for="(item, index) in batchs" v-bind:key="index">
        <el-button link type="primary" :disabled="item.disabled ? item.disabled : false" @click="batchClick(item)">
          {{ item.name }}
          <el-tooltip
            :show-after="500"
            v-if="item.tipContent"
            effect="light"
            :content="item.tipContent"
            placement="top"
          >
            <i class="MC_iconfont MC_icon-yiwen-mian"></i>
          </el-tooltip>
        </el-button>
        <div v-if="index !== batchs.length - 1" class="line"></div>
      </div>
      <span class="MC_iconfont MC_icon-zhuangtai-guanbi oprate-close" @click="cancelSelectFun"></span>
    </div>
    <!-- 翻页 -->
    <template v-if="showPagination">
      <el-pagination
        class="pages"
        :disabled="isAllCheck"
        @current-change="handleCurrentChange"
        @size-change="handleSizeChange"
        :current-page="pagingData.page"
        :page-sizes="[10, 20, 50]"
        :page-size="pagingData.limit"
        layout="total, sizes, prev, pager, next, jumper"
        :total="pagingData.total"
      >
      </el-pagination>
    </template>
  </div>
</template>

<script lang="ts">
/**
 * 可改变表头宽度的table
 * 使用参数参考element-plus el-table
 */
import { defineComponent, reactive, computed, toRefs, watch, getCurrentInstance, onMounted, onUpdated } from 'vue'
import searchCheckbox from './search-checkbox/index.vue'
import cloneDeep from 'lodash/cloneDeep'
const defaultPaging = {
  total: 0,
  'page-size': 10,
  'page-sizes': [5, 10, 30],
  'current-page': 1
}
export default defineComponent({
  name: 'ResizeTable',
  components: { searchCheckbox },
  props: {
    topHeight: {
      // 表格上面除了提示和搜索的高度 用在计算表格动态高度
      type: Number,
      default: 0
    },
    showPagination: {
      // 是否展示翻页，默认展示
      type: Boolean,
      default: true
    },
    headersConfig: {
      // 是否展示配置表头，默认不展示
      type: Boolean,
      default: false
    },
    headers: {
      // 表头数据
      type: Array,
      default: () => []
    },
    data: {
      // 表格数据
      type: Array,
      default: () => []
    },
    pagingData: {
      // 分页
      type: Object,
      default: defaultPaging
    },
    selection: {
      // 是否展示表格前面的多选框
      type: Boolean,
      default: false
    },
    batchs: {
      // 批量操作
      type: Array,
      default: () => []
    },
    showIsAllCheckBox: {
      // 批量操作的全选
      type: Boolean,
      default: true
    },
    rowKey: {
      // 行数据的 Key
      type: String,
      default: ''
    },
    light: {
      // 是否要高亮当前行
      type: Boolean,
      default: true
    },
    height: {
      // 表格高度，用来固定表头
      type: String,
      default: ''
    },
    dynamic: {
      type: Boolean,
      default: false
    }
  },
  emits: ['onPageChange', 'onPageSizeChange', 'onCheckHeadersChange', 'onBatchClick'],
  setup(props, { emit }) {
    const instance: any = getCurrentInstance()
    const state = reactive({
      checkList: [], // 表头数据
      isClick: false, // 表头操作按钮的显隐
      isAllCheck: false, // 是否全选
      showLoading: false, // loading...
      pageSelect: {} as any, // 根据选择存储数据
      selectList: [], // 选中数据
      checkInit: false, // 是否初始化
      tableHeight: 0
    })

    const selectLength: any = computed(() => {
      // 选中的数量
      let length: any = 0
      Object.keys(state.pageSelect).forEach((page) => {
        length += state.pageSelect[page].length
      })
      return length
    })

    const getHeadersShowLength: any = computed(() => {
      // 表头show的数量
      let length = 0
      state.checkList.forEach((item: any) => {
        if (item.show) {
          length++
        }
      })
      return length
    })

    const showBatch = computed(() => {
      return selectLength.value > 0 || state.isAllCheck
    })

    watch([() => showBatch.value], () => {
      handleSetTabelHeight()
    })

    const handleSetTabelHeight = () => {
      const con: any = instance?.refs.configTableCon
      if (con) {
        const tableH = con.offsetHeight
        if (selectLength.value && props.showPagination) {
          // 分页+select 分页52 select52
          state.tableHeight = tableH - 52 - 52 - props.topHeight
        } else if (props.showPagination && !selectLength.value) {
          // 分页
          state.tableHeight = tableH - 52 - props.topHeight
        } else if (!props.showPagination && selectLength.value) {
          state.tableHeight = tableH - 52 - props.topHeight
        } else {
          state.tableHeight = tableH - props.topHeight
        }
      }
    }

    const handleResizeChange = () => {
      ;(window as any).addEventListener('resize', () => {
        handleSetTabelHeight()
      })
    }

    onUpdated(() => {
      handleSetTabelHeight()
    })

    onMounted(() => {
      handleResizeChange()
    })

    function cancelSelectFun() {
      // 取消选择
      state.pageSelect = {} // 清空当前选择项
      state.isAllCheck = false
      clearSelection() // 取消checked
    }

    function checkAllData(data: any) {
      // 选择全部
      state.isAllCheck = data
      if (data) {
        // 全选
        state.pageSelect[props.pagingData.page] = cloneDeep(props.data) // 存储当页数据
        clearSelection() // 先取消选择
        props.data.forEach((item: any) => {
          // 当前页全选
          instance?.refs.tableRef.toggleRowSelection(item, true) // 当前页全选
        })
      } else {
        // 取消全选
        cancelSelectFun()
      }
    }

    function handleCurrentChange(page: any) {
      // 翻页
      emit('onPageChange', page)
    }

    function handleSizeChange(size: any) {
      // limit变化
      emit('onPageSizeChange', size)
    }

    function handleCheckChange(Datalist: any, isInit: any) {
      // 表头配置变化
      if (state.checkInit && isInit === true && !props.dynamic) {
        // 是否是初始化
        return
      }
      state.showLoading = true
      setTimeout(() => {
        state.showLoading = false
      }, 400)
      if (isInit === true) {
        state.checkInit = true
      }
      state.checkList = Datalist
      emit('onCheckHeadersChange', Datalist, isInit)
    }

    function arraySpanMethod({ row, column, rowIndex, columnIndex }: any) {
      // 合并
      let oprateIndex
      if (props.selection) {
        oprateIndex = getHeadersShowLength.value + 1
      } else {
        oprateIndex = getHeadersShowLength.value
      }
      if (columnIndex === oprateIndex) {
        return [1, 2]
      }
    }

    function selectChange(selection: any) {
      // 单独选择某一个
      state.isAllCheck = false
      if (selection && selection.length === props.pagingData.total) {
        state.isAllCheck = true
      }
      state.pageSelect[props.pagingData.page] = cloneDeep(selection)
      handleSetTabelHeight()
    }

    function selectAll(selection: any) {
      // 单页全选
      if (selection && selection.length === props.pagingData.total && props.showIsAllCheckBox) {
        state.isAllCheck = true
      }
      if (selection) {
        state.pageSelect[props.pagingData.page] = cloneDeep(selection)
        if (selection.length <= 0) {
          state.isAllCheck = false
        }
      } else {
        state.pageSelect[props.pagingData.page] = []
        state.isAllCheck = false
      }
    }

    function clearSelection() {
      // 清空选择
      instance?.refs.tableRef.clearSelection()
    }

    function batchClick(item: any) {
      // 批量操作
      const selectList: string[] = []
      Object.keys(state.pageSelect).forEach((page) => {
        if (state.pageSelect[page].length > 0) {
          state.pageSelect[page].forEach((pageItem: any) => {
            selectList.push(pageItem._id)
          })
        }
      })
      emit('onBatchClick', item.action, props.showIsAllCheckBox ? state.isAllCheck || selectList : selectList)
    }

    watch(
      // 监听表格数据变化
      () => props.data,
      (newVal: any) => {
        clearSelection()
        const rows = cloneDeep(state.pageSelect[props.pagingData.page])
        if (rows && rows.length > 0) {
          rows.forEach((row: any) => {
            newVal.forEach((lItem: any, index: any) => {
              if (lItem._id === row._id) {
                instance?.refs.tableRef.toggleRowSelection(newVal[index], true)
              }
            })
          })
        }
      }
    )

    return {
      selectLength,
      cancelSelectFun,
      checkAllData,
      handleCurrentChange,
      handleSizeChange,
      handleCheckChange,
      arraySpanMethod,
      selectChange,
      selectAll,
      batchClick,
      ...toRefs(state)
    }
  }
})
</script>

<style lang="stylus" scoped>
.resize-table
  position absolute
  height 100%
  width 100%
  .el-dropdown-link
    width 24px
    height 24px
    border-radius 4px
    text-align center
    line-height 24px
    .MC_icon-shezhi
      color rgba(0, 0, 0, .88)
  :deep(){
    .sort-caret {
      left 70px
    }
    .el-table-column--selection {
      .cell {
        display flex
      }
      .el-checkbox__inner {
        border-color rgba(0, 0, 0, 0.38)
      }
      .el-checkbox__input.is-checked .el-checkbox__inner {
        border-color var(--mc-main-color)
      }
    }
  }
.MC_icon-zidingyi
  cursor pointer
.icon-active
  color #008cee
.batch-oprate
  height 36px
  line-height 36px
  background rgba(30, 99, 245, 0.1)
  border-radius 4px
  display flex
  align-items center
  padding 0 18px 0
  position relative
  margin-top 16px
  .selected-count
    margin 0 24px 0 18px
    color #303753
    .selectedNum
      color var(--mc-main-color)
      margin 0 4px 0
  .selectedBtn
    display flex
    align-items: center
    .line
      width 1px
      height 10px
      margin 0 8px
      background rgba(30, 99, 245, 0.3)
  .oprate-close
    color var(--mc-main-color)
    cursor pointer
    position absolute
    right 18px
.pages
  display flex
  justify-content flex-end
  height 48px
  align-items center
:deep(.el-table__empty-text)
  line-height 20px
  img
    margin-top 10px
</style>
